package bb.lanxing.mvp.model;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.litepal.LitePal;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

import android.database.Cursor;

import bb.lanxing.model.database.RouteBook;
import bb.lanxing.model.database.RouteBookPoint;
import bb.lanxing.model.database.RouteSlope;
import bb.lanxing.model.json.ServerJson;
import bb.lanxing.mvp.model.i.IRouteSlopeModel;
//import bb.lanxing.network.BiciHttpClient;
import bb.lanxing.network.MyHttpClient;
import bb.lanxing.network.NetSubscribe;
import bb.lanxing.util.RouteBookUtil;
import rx.Observable;
import rx.functions.Func1;
import rx.schedulers.Schedulers;

public class RouteSlopeModelImpl implements IRouteSlopeModel {
    @Override
    public Observable<List<RouteBookPoint>> queryRoutePoint(long routeId) {
        return Observable.just(routeId).subscribeOn(Schedulers.io())
                .flatMap(new Func1<Long, Observable<List<RouteBookPoint>>>() {
                    @Override
                    public Observable<List<RouteBookPoint>> call(Long routeId2) {
                        // sun, change to use new database

                        Cursor query = LitePal.getDatabase().query("lushu", new String[] { "altitudestring" }, "id=?",
                                new String[] { String.valueOf(routeId2) }, null, null, null);
                        if (!query.moveToFirst()) {
                            return Observable.error(new IllegalArgumentException("No Lushu found with ID:" + routeId2));
                        }
                        String string = query.getString(0);
                        query.close();
                        try {
                            return Observable.just(RouteBookUtil.parseAltitudeData(new JSONArray(string)));
                        } catch (JSONException e) {
                            return Observable.error(e);
                        }

                        // Cursor query = SugarRecord.getSugarDb().getDB().query("lushu", new
                        // String[]{"altitude_string"}, "id=?", new String[]{String.valueOf(routeId2)}, null, null,
                        // null);
                        // if (!query.moveToFirst()) {
                        // return Observable.error(new IllegalArgumentException("No Lushu found with ID:" + routeId2));
                        // }
                        // String string = query.getString(0);
                        // query.close();
                        // try {
                        // return Observable.just(LushuUtil.parseAltitudeData(new JSONArray(string)));
                        // } catch (JSONException e) {
                        // return Observable.error(e);
                        // }

                        // return null;
                    }
                });
    }

    @Override
    public Observable<List<RouteSlope>> queryRouteSlope(long routeId) {
        return Observable.just(routeId).subscribeOn(Schedulers.io()).flatMap(routeId2 -> {
            // sun, change to use new database
            return Observable.just(LitePal.where("route_id=?", String.valueOf(routeId2)).find(RouteSlope.class));

            // return Observable.just(SugarRecord.find(RouteSlope.class, "route_id=?", String.valueOf(routeId2)));

            // return null;

        });
    }

    @Override
    public Observable<List<RouteSlope>> requestRouteSlop(final long lushuId, int sample) {
        return Observable.create(new NetSubscribe(MyHttpClient.requestRouteSlope(lushuId, sample)))
                .subscribeOn(Schedulers.io()).flatMap(new Func1<String, Observable<List<RouteSlope>>>() {
                    @Override
                    public Observable<List<RouteSlope>> call(String s) {
                        ServerJson serverJson = (ServerJson) JSON.parseObject(s, ServerJson.class);
                        if (serverJson.getResult() == 1) {
                            JSONObject parseObject = JSON.parseObject(serverJson.getData());
                            RouteBook byServerId = RouteBook.getByServerId(lushuId);
                            if (byServerId == null) {
                                return Observable.error(new IllegalStateException(
                                        "Not found lushu in local db with server_id#" + lushuId));
                            }
                            long longValue = byServerId.getId();
                            List<RouteSlope> parseArray =
                                    JSON.parseArray(parseObject.getString("lushuslope"), RouteSlope.class);
                            for (RouteSlope routeSlope : parseArray) {
                                routeSlope.setRouteId(longValue);
                            }
                            Collections.sort(parseArray, new Comparator<RouteSlope>() {
                                @Override
                                public int compare(RouteSlope o1, RouteSlope o2) {
                                    if (o1.getNum() > o2.getNum()) {
                                        return 1;
                                    }
                                    return o1.getNum() < o2.getNum() ? -1 : 0;
                                }
                            });
                            return Observable.just(parseArray);
                        }
                        return Observable
                                .error(new IllegalStateException("get route slope failed ! #" + serverJson.getData()));
                    }
                });
    }

    @Override
    public Observable<List<RouteSlope>> saveSlopes(List<RouteSlope> routeSlopes) {
        return Observable.just(routeSlopes).subscribeOn(Schedulers.io())
                .flatMap(new Func1<List<RouteSlope>, Observable<List<RouteSlope>>>() {
                    @Override
                    public Observable<List<RouteSlope>> call(final List<RouteSlope> slopes) {
                        // sun, change to use new database

                        try {
                            LitePal.beginTransaction();

                            for (RouteSlope routeSlope : slopes) {
                                routeSlope.save();
                            }

                            LitePal.setTransactionSuccessful();
                        } catch (Exception e) {
                            e.printStackTrace();

                        } finally {
                            LitePal.endTransaction();

                        }

                        // SugarTransactionHelper.doInTansaction(new SugarTransactionHelper.Callback() {
                        // @Override
                        // public void manipulateInTransaction() {
                        // for (RouteSlope routeSlope : slopes) {
                        // routeSlope.save();
                        // }
                        // }
                        // });
                        return Observable.just(slopes);
                    }
                });
    }
}
